package lpc

import (
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/exec"
	"strings"

	"gitee.com/dark.H/go-remote-repl/datas"
	"github.com/Qingluan/Tunnel/tcp"
)

func (apiinfo *APIInfo) StartPiepTo(argsS string, outer net.Conn) {

	if err := apiinfo.CheckPermission(); err != nil {
		datas.JsonErr(err, outer)
		return
	}

	cmdArgs := datas.SmartChooseCmdArgs(apiinfo.Executale, apiinfo.BinFilePath, argsS, outer)
	choose, err := datas.Choose(outer, "run/background?", "run", "as task")
	if err != nil {
		datas.JsonErr(err, outer)
		return
	}
	switch choose {
	case "run":
		cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
		cmd.Env = os.Environ()

		stdin, err := cmd.StdinPipe()
		if err != nil {
			datas.JsonErr(err, outer)
			return
		}
		output, err := cmd.StdoutPipe()

		if err != nil {
			// errMsg, _ := ioutil.ReadAll(erroutput)
			datas.JsonErr(fmt.Errorf("%v || detail : %s", err, "stdout err , maybe your process include some function need stdin or stdout"), outer)

			return
		}

		erroutput, err := cmd.StderrPipe()
		if err != nil {
			datas.JsonErr(fmt.Errorf("%v || detail : %s", err, "stdout err , maybe your process include some function need stdin or stdout"), outer)
			return
		}
		if err = cmd.Start(); err != nil {
			// datas.JsonErr(errors.New("run:"+))
			errMsg, _ := ioutil.ReadAll(erroutput)
			datas.JsonErr(fmt.Errorf("%v || detail : %s", err, string(errMsg)), outer)
			// return
		}
		sess := NewSession(strings.Join(cmdArgs, " "), "what")
		sess.PID = cmd.Process.Pid
		sess.State = "starting"
		SessionUpdate(sess)
		defer func() {
			sess.State = "Finished"
			SessionUpdate(sess)
		}()

		log.Println("Start Cmd:", cmdArgs[0], strings.Join(cmdArgs[1:], " "))
		if err != nil {
			errMsg, _ := ioutil.ReadAll(erroutput)
			datas.JsonErr(fmt.Errorf("%v || detail : %s", err, string(errMsg)), outer)
			return
		}
		go tcp.Copy(outer, erroutput)
		go tcp.Copy(stdin, outer)
		tcp.Copy(outer, output)
		cmd.Wait()
		// time.Sleep(100 * time.Microsecond)

	case "as task":
		shell := strings.Join(cmdArgs, " ")
		sess := NewSession(shell, shell)
		go sess.Run(func(outlog string) {
			log.Println(datas.Green("[+] Finished:", sess.Id))
		}, func(err error) {
			datas.JsonErr(err, outer)
		})
		datas.JsonSend(datas.Data{
			"Code": true,
			// "Used":      time.Now().Sub(),
			"SessionId": sess.Id,
		}, outer)
	}
}

func (apiinfo *APIInfo) CheckPermission() error {
	_, err := os.Stat(apiinfo.BinFilePath)
	if err != nil {
		return err
	}
	return os.Chmod(apiinfo.BinFilePath, os.ModePerm)

}
